package com.sproutcat.security;


import org.springframework.util.ResourceUtils;
import org.springframework.util.StreamUtils;

import javax.crypto.Cipher;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

import static java.nio.charset.StandardCharsets.UTF_8;

/**
 * RSA 非对称加密用例
 *
 * @author tzg
 */
public class RsaSample {

    public static void main(String[] args) throws Exception {
        String testDate = "[{\n" +
                "  \"name\": \"test1\",\n" +
                "  \"age\": 21\n" +
                "},{\n" +
                "  \"name\": \"test2\",\n" +
                "  \"age\": 26\n" +
                "}]";
        //String testDate = "Hello world!";

        // 创建密钥对（公钥与私钥）
        RsaKey keyPair = generateRsaKeys();
        String encryptData = encryptByPublicKey(testDate, keyPair.getPublicKey());
        System.out.println("RSA 公钥加密结果: " + encryptData);
        System.out.println();
        System.out.println("RSA 私钥解密结果: " + decryptByPrivateKey(encryptData, keyPair.getPrivateKey()));
    }

    //=========================== RSA 基础代码 =============================================
    public static final String KEY_ALGORITHM = "RSA";
//    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
//
//    public static String sign(byte[] data, String privateKey) throws GeneralSecurityException {
//        byte[] keyBytes = Base64.getDecoder().decode(privateKey.getBytes(UTF_8));
//        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
//        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//        PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
//        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
//        signature.initSign(priKey);
//        signature.update(data);
//        return new String(Base64.getEncoder().encode(signature.sign()), UTF_8);
//    }
//
//    public static boolean verify(byte[] data, String publicKey, String sign) throws GeneralSecurityException {
//        byte[] keyBytes = Base64.getDecoder().decode(publicKey.getBytes(UTF_8));
//        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
//        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//        PublicKey pubKey = keyFactory.generatePublic(keySpec);
//        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
//        signature.initVerify(pubKey);
//        signature.update(data);
//        return signature.verify(Base64.getDecoder().decode(sign));
//    }

    public static String decryptByPrivateKey(String data, String key) throws GeneralSecurityException {
        byte[] keyBytes = Base64.getDecoder().decode(key.getBytes(UTF_8));
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(2, privateKey);
        byte[] decodeData = Base64.getDecoder().decode(data);
        return new String(cipher.doFinal(decodeData), UTF_8);
    }

//    public static byte[] decryptByPrivateKey(String data, String key) throws GeneralSecurityException {
//        return decryptByPrivateKey(Base64.getDecoder().decode(data.getBytes(UTF_8)), key);
//    }

//    public static byte[] decryptByPublicKey(byte[] data, String key) throws GeneralSecurityException {
//        byte[] keyBytes = Base64.getDecoder().decode(key);
//        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
//        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//        Key publicKey = keyFactory.generatePublic(x509KeySpec);
//        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
//        cipher.init(2, publicKey);
//        return cipher.doFinal(data);
//    }

    /**
     * 用公钥加密数据
     *
     * @param data
     * @param key
     * @return
     * @throws GeneralSecurityException
     */
    public static String encryptByPublicKey(String data, String key) throws GeneralSecurityException {
        byte[] keyBytes = Base64.getDecoder().decode(key);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicKey = keyFactory.generatePublic(x509KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(1, publicKey);
        byte[] rsaEncode = cipher.doFinal(data.getBytes(UTF_8));
        byte[] base64Encode = Base64.getEncoder().encode(rsaEncode);
        return new String(base64Encode, UTF_8);
    }

//    public static byte[] encryptByPrivateKey(byte[] data, String key) throws GeneralSecurityException {
//        byte[] keyBytes = Base64.getDecoder().decode(key);
//        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
//        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//        Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
//        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
//        cipher.init(1, privateKey);
//        return cipher.doFinal(data);
//    }

    /**
     * 生成 RSA 公私钥对
     *
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static RsaKey generateRsaKeys() throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        keyPairGen.initialize(1024);
        KeyPair keyPair = keyPairGen.generateKeyPair();
        String publicKey = new String(Base64.getEncoder().encode(keyPair.getPublic().getEncoded()), UTF_8);
        String privateKey = new String(Base64.getEncoder().encode(keyPair.getPrivate().getEncoded()), UTF_8);
        return new RsaKey(publicKey, privateKey);
    }

}
